//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// lru_replacer.cpp
//
// Identification: src/buffer/lru_replacer.cpp
//
// Copyright (c) 2015-2019, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "buffer/lru_replacer.h"

namespace bustub {

LRUReplacer::LRUReplacer(size_t num_pages) : max_repl_size(num_pages) {}

LRUReplacer::~LRUReplacer() = default;

bool LRUReplacer::Victim(frame_id_t *frame_id) {
  lru_mutex.lock();

  if (lruList.empty()) {
    frame_id = nullptr;
    lru_mutex.unlock();
    return false;
  }

  *frame_id = lruList.back();

  lruList.pop_back();
  lruMap.erase(*frame_id);

  lru_mutex.unlock();
  return true;
}

void LRUReplacer::Pin(frame_id_t frame_id) {
  lru_mutex.lock();

  if (lruMap.count(frame_id)) {
    framePtr it = lruMap[frame_id];
    frame_id_t id = *it;
    lruList.erase(it);
    lruMap.erase(id);
  }

  lru_mutex.unlock();

  return;
}

void LRUReplacer::Unpin(frame_id_t frame_id) {
  lru_mutex.lock();

  if (lruMap.count(frame_id)) {
    lru_mutex.unlock();
    return;
  }

  if (lruList.size() == max_repl_size) {
    Pin(lruList.back());
  }

  lruList.push_front(frame_id);
  lruMap[frame_id] = lruList.begin();

  lru_mutex.unlock();
}

size_t LRUReplacer::Size() {
  lru_mutex.lock();
  size_t tmp = lruList.size();
  lru_mutex.unlock();

  return tmp;
}

}  // namespace bustub
